#ifndef _TRACE_H_
#define _TRACE_H_

/*
	Trace.h and Trace.cpp provide low level api for ray tracing
*/

#include "../xobjIO/glMesh.h"

#include "../cuCommon/cuTypes.h"
#include "../cuCommon/cuBuffer.h"
#include "../cuCommon/cuMath.h"
#include "../cuCommon/cuDefine.h"

#include "../rtCommon/RegularGrid.h"
#include "../rtCommon/C_Camera.h"
#include "../rtCommon/Ray.h"
#include "../rtCommon/Triangle.h"
#include "../rtCommon/Intersect.h"
#include "../rtCommon/SpatialTree.h"

#ifdef _DEBUG
#define USE_BENCHMARK
#endif
#include "../rtCommon/Benchmark.h"


#define RT_PERSPECTIVE									0x0001
#define RT_ORTHOGONAL										0x0002
#define RT_DEPTH_OF_FIELD               0x0004

#define RT_SS_1x                        0x0001
#define RT_SS_2x                        0x0002

#define RT_LINEAR									      0x0001

void mpGenerateEyeRays(IN		C_Camera  & camera, 
											 IN		int2			& resolution,
											 IN		int2			& sample,
											 IN		uint32			type,
											 OUT	float4		* pRayO,
											 OUT	float4		* pRayD);

//////////////////////////////////////////////////////////////////////////
/// Resolve render target code
/// because CUDA doesn't support basic operations with built-in types
/// I have to duplicate function names for each vector size separately
//////////////////////////////////////////////////////////////////////////
template<class T>
void mpResolveBuffer_v4(IN  int2     & resolution,
												IN  int2     & sample,
												IN  uint32     filter,
												OUT T        * pIn,
												OUT T        * pOut);
template<class T>
void mpResolveBuffer_v3(IN  int2     & resolution,
												IN  int2     & sample,
												IN  uint32     filter,
												OUT T        * pIn,
												OUT T        * pOut);

template<class T>
void mpResolveBuffer_v2(IN  int2     & resolution,
												IN  int2     & sample,
												IN  uint32     filter,
												OUT T        * pIn,
												OUT T        * pOut);

template<class T>
void mpResolveBuffer_v1(IN  int2     & resolution,
												IN  int2     & sample,
												IN  uint32     filter,
												OUT T        * pIn,
												OUT T        * pOut);

//////////////////////////////////////////////////////////////////////////
/// Explicit declaration of mpResolveBuffer_vx template functions
//////////////////////////////////////////////////////////////////////////

template 
void mpResolveBuffer_v4<uchar4>(IN  int2   & resolution, 
																IN  int2   & sample, 
																IN  uint32   filter, 
																OUT uchar4 * pIn, 
																OUT uchar4 * pOut);

template 
void mpResolveBuffer_v4<float4>(IN  int2   & resolution, 
																IN  int2   & sample, 
																IN  uint32   filter, 
																OUT float4 * pIn, 
																OUT float4 * pOut);


void mpGenerateEyeRay(IN  C_Camera & camera,
											IN  int2    & rp,
											IN  uint32    type, 
										  IN  int       x,
											IN  int       y,
											OUT float3  & rayO,
											OUT float3  & rayD,
											OUT int     & iRay);

void mpTrace(IN  float4  * pRayO,
						 IN  float4  * pRayD,
						 IN  uint32    nRay,
						 IN  CglMesh * pMesh,
						 IN  uint32    nMesh,
						 OUT float   * pTmin, 
						 OUT int     * pId,
						 OUT uchar4  * pRgba8);

void mpTraceKdTree(IN  CSpatialTree * pKd,
									 IN  S_Box				& box,
									 IN  float4       * pRayO,
									 IN  float4       * pRayD, 
									 IN  int32          nRay,
									 IN  float4       * pPosition,
									 IN  int32        * pFace,
									 IN  uint32       * pIndex,
									 OUT float        * pTmin, 
									 OUT int2         * pId, 
									 OUT uchar4       * pRgba8);

void mpTraceKdTree(IN  CSpatialTree * pKd,
									 IN  S_Box				& box,
									 IN  float3       & orig,
									 IN  float3       & dir,
									 IN  int32          iRay,
									 IN  float4       * pPosition,
									 IN  int32        * pFace,
									 IN  uint32       * pIndex,
									 OUT float        * pTmin, 
									 OUT int2         * pId, 
									 OUT uchar4       * pRgba8);

void mpTraceBVHTree(IN  CSpatialTree * pBVH,  
										IN  float4       * pRayO, 
										IN  float4       * pRayD, 
										IN  int32          nRay,
										IN  float4       * pPosition, 
										IN  int32        * pFace, 
										IN  uint32       * pIndex,
										OUT float        * pTmin, 
										OUT int2         * pId, 
										OUT uchar4       * pRgba8);

void mpTraceBVHTree(IN  CSpatialTree * pBVH,  
										IN  float3       & orig,
										IN  float3       & dir,
										IN  int32          iRay,
										IN  float4       * pPosition, 
										IN  int32        * pFace, 
										IN  uint32       * pIndex,
										OUT float        * pTmin, 
										OUT int2         * pId, 
										OUT uchar4       * pRgba8);

void cuGenerateEyeRays(IN  C_Camera  & camera, 
											 IN  int2     & resolution,
											 IN  int2     & sample,
											 IN  uint32     type,
											 OUT float4   * pRayO,
											 OUT float4   * pRayD);


void cuTrace(IN  float4  * pRayO,
						 IN  float4  * pRayD, 
						 IN  uint32    nRay,
						 IN  CglMesh * pMesh,
						 IN  uint32    nMesh,
						 OUT float   * pTmin, 
						 OUT int2    * pId, 
						 OUT uchar4  * pRgba8);

void cuTraceKdTree(IN  float2    * pKd,
									 IN  S_Box    & box, 
									 IN  float4    * pRayO,
									 IN  float4    * pRayD, 
									 IN  uint32      nRay,
									 IN  float4    * pPosition,
									 IN  int32     * pFace,
									 IN  uint32    * pIndex,
									 OUT float     * pTmin, 
									 OUT int2      * pId, 
									 OUT uchar4    * pRgba8);

#endif // _TRACE_H_